package cn.iocoder.yudao.module.trade.order.service.calculator;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.business.basic.convert.BigDecimalConvert;
import cn.iocoder.yudao.framework.common.exception.Assertions;
import cn.iocoder.yudao.framework.common.exception.KnownServiceException;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.module.api.dine.enums.DineAttributeEnum;
import cn.iocoder.yudao.module.api.dine.vo.DineConfigVO;
import cn.iocoder.yudao.module.api.product.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.api.product.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.api.product.spu.enums.ProductPriceModeEnum;
import cn.iocoder.yudao.module.api.promotion.groupon.dto.GrouponPackageRespDTO;
import cn.iocoder.yudao.module.api.shop.category.eums.ShopCategoryCodeEnum;
import cn.iocoder.yudao.module.api.trade.delivery.enums.DeliveryTypeEnum;
import cn.iocoder.yudao.module.api.trade.order.enums.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.order.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.order.bo.TradePriceCalculateRespBO;
import cn.iocoder.yudao.module.trade.order.dal.dataobject.TradeOrderItemDO;
import jakarta.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
import static java.util.Collections.singletonList;

/**
 * {@link TradePriceCalculator} 的工具类
 * 主要实现对 {@link TradePriceCalculateRespBO} 计算结果的操作
 *
 * @author 芋道源码
 */
@Slf4j
public class TradePriceCalculatorHelper {

    public static TradePriceCalculateRespBO buildCalculateResponse(TradePriceCalculateReqBO param, List<ProductSpuRespDTO> spuList, List<ProductSkuRespDTO> skuList, @Nullable GrouponPackageRespDTO grouponPackage, DineConfigVO dineConfig) {
        TradePriceCalculateRespBO result = new TradePriceCalculateRespBO();
        result.setDineConfig(dineConfig);
        result.setDinePeoples(param.getDinePeoples());
        result.setPromotions(new ArrayList<>());
        result.setGiveCouponTemplateCounts(new LinkedHashMap<>());
        List<TradePriceCalculateReqBO.Item> items = param.getItems();
        if (CollUtil.isEmpty(items)) {
            items = new ArrayList<>();
        }
        result.setItems(new ArrayList<>(items.size()));
        result.setTotalPoint(0);
        result.setDeductPoint(0);
        result.setTotalCryptocurrency(BigDecimalConvert.INSTANCE.convert(0));
        result.setDeductCryptocurrency(BigDecimalConvert.INSTANCE.convert(0));
        result.setFirstOrderDiscount(0d);
        result.setPrice(new TradePriceCalculateRespBO.Price());
        if (grouponPackage != null) {
            result.setType(TradeOrderTypeEnum.GROUPON.getType());
            result.setShopId(grouponPackage.getShopId());
            result.setSupportDeliveryTypes(CollUtil.newArrayList(DeliveryTypeEnum.NONE.getType(), DeliveryTypeEnum.VERIFY.getType()));
            result.setGrouponPackageId(param.getGrouponPackageId());
            result.setGrouponPackage(grouponPackage);
            TradePriceCalculateRespBO.OrderItem orderItem = TradePriceCalculateRespBO.OrderItem.empty();
            orderItem.setSelected(true); // 进入价格计算一定全部选中
            orderItem.setSpuName(grouponPackage.getName()); // ！！！重要！！！订单站内信会用到 spuName，故此适配
            orderItem.setPicUrl(grouponPackage.getPicUrl());
            orderItem.setCount(1);
            orderItem.setUnitValue(1);
            orderItem.setUnitName("份");
            orderItem.setSkuPrice(grouponPackage.getOriginPrice());
            orderItem.setSkuCostPrice(grouponPackage.getCostPrice());
            orderItem.setSkuVipPrice(grouponPackage.getVipPrice());
            orderItem.setSkuWholesaleForRetailPrice(grouponPackage.getWholesaleForRetailPrice());
            orderItem.setSkuPointDeductCount(grouponPackage.getPointDeductCount());
            orderItem.setSkuCryptocurrencyDeductCount(grouponPackage.getCryptocurrencyDeductCount());
            orderItem.setPayPrice(grouponPackage.getPrice()); // ！！！重要！！！订单分佣会用到 payPrice，故此适配
            orderItem.setProperties(new ArrayList<>());
            log.trace("[buildCalculateResponse] grouponPackage orderItem: {}", orderItem);
            result.getItems().add(orderItem);
        } else if (CollUtil.isNotEmpty(spuList)) {
            ProductSpuRespDTO spuRespDTO = spuList.get(0);
            result.setType(calculateOrderType(param, spuRespDTO.getType()));
            result.setShopId(spuRespDTO.getShopId());
            // TODO 后面再优化，从所有 SPU 中获取
            //result.setSupportDeliveryTypes(spuRespDTO.getDeliveryTypes());
            Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
            Map<Long, ProductSkuRespDTO> skuMap = convertMap(skuList, ProductSkuRespDTO::getId);
            items.forEach(item -> {
                TradePriceCalculateRespBO.OrderItem orderItem = buildOrderItem(item, skuMap, spuMap, dineConfig);
                if (orderItem == null) {
                    return;
                }
                orderItem.setSelected(true); // 进入价格计算一定全部选中
                log.trace("[buildCalculateResponse] product orderItem: {}", orderItem);
                result.getItems().add(orderItem);
            });
        } else {
            result.setType(TradeOrderTypeEnum.NORMAL.getType());
        }
        recountAllPrice(result);
        recountAllGivePoint(result);
        recountAllGiveCryptocurrency(result);
        recountAllGiveBonus(result);
        if (dineConfig != null) {
            if (result.getPrice().getTotalPrice() < dineConfig.getConsumeThresholdPrice()) {
                throw new KnownServiceException("下单失败：未达到最低消费金额 ¥" + MoneyUtils.fenToYuanStr(dineConfig.getConsumeThresholdPrice()));
            }
        }
        return result;
    }

    /**
     * 基于普通产品构建订单项
     */
    @Nullable
    private static TradePriceCalculateRespBO.OrderItem buildOrderItem(TradePriceCalculateReqBO.Item item, Map<Long, ProductSkuRespDTO> skuMap, Map<Long, ProductSpuRespDTO> spuMap, DineConfigVO dineConfig) {
        ProductSkuRespDTO sku = skuMap.get(item.getSkuId());
        if (sku == null) {
            return null;
        }
        ProductSpuRespDTO spu = spuMap.get(sku.getSpuId());
        if (spu == null) {
            return null;
        }
        Assertions.isTrue(item.getCount() >= spu.getLimitMinQuantity(), "未达到起购数量：" + spu.getLimitMinQuantity());
        // 适配称重计价模式
        if (Objects.equals(spu.getPriceMode(), ProductPriceModeEnum.TOTAL_WEIGHT.getValue())) {
            spu.setUnitName(dineConfig.getWeightUnitName());
            int unitPrice = dineConfig.getVegetableUnitPrice();
            if (Objects.equals(spu.getDishAttribute(), DineAttributeEnum.MEAT.getValue())) {
                unitPrice = dineConfig.getMeatUnitPrice();
            }
            sku.setPrice(spu.getStepQuantity() * unitPrice);
            sku.setVipPrice(sku.getPrice());
            sku.setCostPrice(0);
        }
        // 产品项
        TradePriceCalculateRespBO.OrderItem orderItem = TradePriceCalculateRespBO.OrderItem.empty();
        orderItem.setSpuId(sku.getSpuId());
        orderItem.setSkuId(sku.getId());
        orderItem.setCount(item.getCount());
        orderItem.setUnitValue(spu.getStepQuantity());
        orderItem.setUnitName(spu.getUnitName());
        orderItem.setCartId(item.getCartId());
        orderItem.setSelected(item.getSelected());
        // sku 价格
        log.debug("[buildOrderItem] price={}, costPrice={}, vipPrice={}, wholesalePrice={}, pointDeductCount={}, cryptocurrencyDeductCount={}", sku.getPrice(), sku.getCostPrice(), sku.getVipPrice(), sku.getWholesaleForRetailPrice(), sku.getPointDeductCount(), sku.getCryptocurrencyDeductCount());
        // 价格信息
        orderItem.setSkuPrice(sku.getPrice());
        orderItem.setSkuCostPrice(sku.getCostPrice());
        orderItem.setSkuVipPrice(sku.getVipPrice());
        orderItem.setSkuWholesaleForRetailPrice(sku.getWholesaleForRetailPrice());
        orderItem.setSkuPointDeductCount(sku.getPointDeductCount());
        orderItem.setSkuCryptocurrencyDeductCount(sku.getCryptocurrencyDeductCount());
        orderItem.setPayPrice(sku.getPrice() * item.getCount());
        // sku 信息
        orderItem.setPicUrl(sku.getPicUrl());
        orderItem.setProperties(sku.getProperties());
        orderItem.setWeight(sku.getWeight());
        orderItem.setVolume(sku.getVolume());
        // spu 信息
        orderItem.setSpuName(spu.getName());
        orderItem.setPlatformCategoryId(spu.getPlatformCategoryId());
        orderItem.setCategoryId(spu.getCategoryId());
        orderItem.setDeliveryTypes(spu.getDeliveryTypes());
        orderItem.setDeliveryTemplateId(spu.getDeliveryTemplateId());
        orderItem.setGivePoint(0);
        orderItem.setDeductPoint(0);
        orderItem.setDeductCryptocurrency(0d);
        orderItem.setGiveCryptocurrency(0d);
        orderItem.setGiveBonus(0d);
        if (StrUtil.isBlank(orderItem.getPicUrl())) {
            orderItem.setPicUrl(spu.getPicUrl());
        }

        // 其他信息
        orderItem.setSupplyName(sku.getSupplyName());
        orderItem.setSupplyRelatedSkuId(sku.getSupplyRelatedId());

        return orderItem;
    }

    /**
     * 计算订单类型
     *
     * @param param 计算参数
     * @return 订单类型
     */
    private static Integer calculateOrderType(TradePriceCalculateReqBO param, String productType) {
        if (param.getSeckillActivityId() != null && param.getSeckillActivityId() > 0) {
            return TradeOrderTypeEnum.SECKILL.getType();
        }
        if (param.getCombinationActivityId() != null && param.getCombinationActivityId() > 0) {
            return TradeOrderTypeEnum.COMBINATION.getType();
        }
        if (param.getBargainRecordId() != null && param.getBargainRecordId() > 0) {
            return TradeOrderTypeEnum.BARGAIN.getType();
        }
        if (param.getPointActivityId() != null && param.getPointActivityId() > 0) {
            return TradeOrderTypeEnum.POINT.getType();
        }
        if (param.getGrouponPackageId() != null && param.getGrouponPackageId() > 0) {
            return TradeOrderTypeEnum.GROUPON.getType();
        }
        if (param.getDineDeskId() != null && param.getDineDeskId() > 0) {
            return TradeOrderTypeEnum.FOOD.getType();
        }
        return switch (ShopCategoryCodeEnum.codeOf(productType)) {
            case FOOD -> {
                if (Objects.equals(param.getDeliveryType(), DeliveryTypeEnum.TAKE_OUT.getType())) {
                    yield TradeOrderTypeEnum.TAKE_AWAY.getType();
                } else {
                    yield TradeOrderTypeEnum.FOOD.getType();
                }
            }
            case HOTEL -> TradeOrderTypeEnum.HOTEL.getType();
            case ENTERTAINMENT -> TradeOrderTypeEnum.ENTERTAINMENT.getType();
            case HOUSEKEEPING -> TradeOrderTypeEnum.HOUSEKEEPING.getType();
            case SCENIC -> TradeOrderTypeEnum.SCENIC.getType();
            default -> TradeOrderTypeEnum.NORMAL.getType();
        };
    }

    /**
     * 基于订单项重新计算 price 总价
     *
     * @param result 计算结果
     */
    public static void recountAllPrice(TradePriceCalculateRespBO result) {
        if (result.getGrouponPackage() != null) {
            log.debug("[recountAllPrice] 订单为团购套餐，直接使用团购价格，无需基于订单项重新计算价格");
            return;
        }
        if (CollUtil.isEmpty(result.getItems())) {
            log.debug("[recountAllPrice] 订单项为空，无需基于订单项重新计算价格");
            return;
        }
        // 先重置
        TradePriceCalculateRespBO.Price price = result.getPrice().reset();
        // 再重新合计
        result.getItems().forEach(item -> {
            if (!item.getSelected()) {
                return;
            }
            price.setTotalPrice(price.getTotalPrice() + item.getSkuPrice() * item.getCount());
            price.setTotalCostPrice(price.getTotalCostPrice() + item.getSkuCostPrice() * item.getCount());
            price.setTotalWholesalePrice(price.getTotalWholesalePrice() + item.getSkuWholesaleForRetailPrice() * item.getCount());
            price.setTotalVipPrice(price.getTotalVipPrice() + item.getSkuVipPrice() * item.getCount());
            price.setTotalPointDeductCount(price.getTotalPointDeductCount() + item.getSkuPointDeductCount() * item.getCount());
            price.setTotalCryptocurrencyDeductCount(price.getTotalCryptocurrencyDeductCount() + item.getSkuCryptocurrencyDeductCount() * item.getCount());
            price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice());
            price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice());
            price.setCouponPrice(price.getCouponPrice() + item.getCouponPrice());
            price.setPointPrice(price.getPointPrice() + item.getPointPrice());
            price.setCryptocurrencyPrice(price.getCryptocurrencyPrice() + item.getCryptocurrencyPrice());
            price.setVipPrice(price.getVipPrice() + item.getVipPrice());
            price.setWholesalePrice(price.getWholesalePrice() + item.getWholesalePrice());
            price.setMemberLevelPrice(price.getMemberLevelPrice() + item.getMemberLevelPrice());
            price.setPayPrice(price.getPayPrice() + item.getPayPrice());
        });
    }

    /**
     * 基于订单项，重新计算赠送积分
     *
     * @param result 计算结果
     */
    public static void recountAllGivePoint(TradePriceCalculateRespBO result) {
        Integer sumValue = getSumValue(result.getItems(), item -> item.getSelected() ? item.getGivePoint() : 0, Integer::sum);
        result.setGivePoint(sumValue);
    }

    /**
     * 基于订单项，重新计算赠送联盟豆
     *
     * @param result 计算结果
     */
    public static void recountAllGiveCryptocurrency(TradePriceCalculateRespBO result) {
        Double sumValue = getSumValue(result.getItems(), item -> item.getSelected() ? item.getGiveCryptocurrency() : 0d, Double::sum);
        result.setGiveCryptocurrency(BigDecimalConvert.INSTANCE.convert(sumValue));
    }

    /**
     * 基于订单项，重新计算赠送分红
     *
     * @param result 计算结果
     */
    public static void recountAllGiveBonus(TradePriceCalculateRespBO result) {
        Double sumValue = getSumValue(result.getItems(), item -> item.getSelected() ? item.getGiveBonus() : 0d, Double::sum);
        result.setGiveBonus(BigDecimalConvert.INSTANCE.convert(sumValue));
    }

    /**
     * 重新计算单个订单项的支付金额
     *
     * @param orderItem 订单项
     */
    public static void recountPayPrice(TradePriceCalculateRespBO.OrderItem orderItem) {
        orderItem.setPayPrice(orderItem.getSkuPrice() * orderItem.getCount()
                              - orderItem.getDiscountPrice()
                              + orderItem.getDeliveryPrice()
                              - orderItem.getCouponPrice()
                              - orderItem.getPointPrice()
                              - orderItem.getCryptocurrencyPrice()
                              - orderItem.getVipPrice()
                              - orderItem.getWholesalePrice()
                              - orderItem.getMemberLevelPrice()
        );
    }

    /**
     * 重新计算每个订单项的支付金额
     *
     * @param orderItems 订单项数组
     */
    public static void recountPayPrice(List<TradePriceCalculateRespBO.OrderItem> orderItems) {
        orderItems.forEach(TradePriceCalculatorHelper::recountPayPrice);
    }

    /**
     * 计算已选中的订单项，总支付金额
     *
     * @param orderItems 订单项数组
     * @return 总支付金额
     */
    public static Integer calculateTotalPayPrice(List<TradePriceCalculateRespBO.OrderItem> orderItems) {
        return getSumValue(orderItems,
                orderItem -> orderItem.getSelected() ? orderItem.getPayPrice() : 0, // 未选中的情况下，不计算支付金额
                Integer::sum);
    }

    /**
     * 计算已选中的订单项，总产品数
     *
     * @param orderItems 订单项数组
     * @return 总产品数
     */
    public static Integer calculateTotalCount(List<TradePriceCalculateRespBO.OrderItem> orderItems) {
        return getSumValue(orderItems,
                orderItem -> orderItem.getSelected() ? orderItem.getCount() : 0, // 未选中的情况下，不计算数量
                Integer::sum);
    }

    /**
     * 按照支付金额，返回每个订单项的分摊金额数组
     * 实际上 price 不仅仅可以传递的是金额，也可以是积分。因为它的实现逻辑，就是根据 payPrice 做分摊而已
     *
     * @param orderItems 订单项数组
     * @param price      金额
     * @return 分摊金额数组，和传入的 orderItems 一一对应
     */
    public static List<Integer> dividePrice(List<TradePriceCalculateRespBO.OrderItem> orderItems, Integer price) {
        Integer totalPayPrice = calculateTotalPayPrice(orderItems);
        Assert.notNull(totalPayPrice, "订单项的支付金额不能为空");
        // 遍历每一个，进行分摊
        List<Integer> prices = new ArrayList<>(orderItems.size());
        int remainPrice = price;
        for (int i = 0, n = orderItems.size(); i < n; i++) {
            TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i);
            // 1. 如果是未选中，则分摊为 0
            if (!orderItem.getSelected()) {
                prices.add(0);
                continue;
            }
            // 2. 如果选中，则按照百分比，进行分摊
            int partPrice;
            if (i < orderItems.size() - 1) { // 减一的原因，是因为拆分时，如果按照比例，可能会出现.所以最后一个，使用反减
                partPrice = (int) (price * (1.0D * orderItem.getPayPrice() / totalPayPrice));
                remainPrice -= partPrice;
            } else {
                partPrice = remainPrice;
            }
            Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0");
            prices.add(partPrice);
        }
        return prices;
    }

    /**
     * 计算订单调价价格分摊
     * 和 {@link #dividePrice(List, Integer)} 逻辑一致，只是传入的是 TradeOrderItemDO 对象
     *
     * @param items 订单项
     * @param price 订单支付金额
     * @return 分摊金额数组，和传入的 orderItems 一一对应
     */
    public static List<Integer> dividePrice2(List<TradeOrderItemDO> items, Integer price) {
        Integer total = getSumValue(items, TradeOrderItemDO::getPayPrice, Integer::sum);
        assert total != null;
        // 遍历每一个，进行分摊
        List<Integer> prices = new ArrayList<>(items.size());
        int remainPrice = price;
        for (int i = 0; i < items.size(); i++) {
            TradeOrderItemDO orderItem = items.get(i);
            int partPrice;
            if (i < items.size() - 1) { // 减一的原因，是因为拆分时，如果按照比例，可能会出现.所以最后一个，使用反减
                partPrice = (int) (price * (1.0D * orderItem.getPrice() / total));
                remainPrice -= partPrice;
            } else {
                partPrice = remainPrice;
            }
            prices.add(partPrice);
        }
        return prices;
    }

    /**
     * 添加团购套餐的营销明细
     *
     * @param result        价格计算结果
     * @param grouponPackage 团购套餐
     * @param id            营销编号
     * @param name          营销名字
     * @param description   满足条件的提示
     * @param type          营销类型
     * @param discountPrice 优惠价格（总）
     */
    public static void addPromotion(TradePriceCalculateRespBO result, GrouponPackageRespDTO grouponPackage,
                                    Long id, String name, Integer type, String description, Integer discountPrice) {
        TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion();
        promotion.setId(id);
        promotion.setName(name);
        promotion.setType(type);
        promotion.setTotalPrice(grouponPackage.getOriginPrice());
        promotion.setDiscountPrice(discountPrice);
        promotion.setItems(new ArrayList<>());
        promotion.setMatch(true);
        promotion.setDescription(description);
        result.getPromotions().add(promotion);
    }

    /**
     * 添加【匹配】单个 OrderItem 的营销明细
     *
     * @param result        价格计算结果
     * @param orderItem     单个订单产品 SKU
     * @param id            营销编号
     * @param name          营销名字
     * @param description   满足条件的提示
     * @param type          营销类型
     * @param discountPrice 单个订单产品 SKU 的优惠价格（总）
     */
    public static void addPromotion(TradePriceCalculateRespBO result, TradePriceCalculateRespBO.OrderItem orderItem,
                                    Long id, String name, Integer type, String description, Integer discountPrice) {
        addPromotion(result, singletonList(orderItem), id, name, type, description, singletonList(discountPrice));
    }

    /**
     * 添加【匹配】多个 OrderItem 的营销明细
     *
     * @param result         价格计算结果
     * @param orderItems     多个订单产品 SKU
     * @param id             营销编号
     * @param name           营销名字
     * @param description    满足条件的提示
     * @param type           营销类型
     * @param discountPrices 多个订单产品 SKU 的优惠价格（总），和 orderItems 一一对应
     */
    public static void addPromotion(TradePriceCalculateRespBO result, List<TradePriceCalculateRespBO.OrderItem> orderItems,
                                    Long id, String name, Integer type, String description, List<Integer> discountPrices) {
        // 创建营销明细 Item
        List<TradePriceCalculateRespBO.PromotionItem> promotionItems = new ArrayList<>(discountPrices.size());
        for (int i = 0; i < orderItems.size(); i++) {
            TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i);
            TradePriceCalculateRespBO.PromotionItem promotionItem = new TradePriceCalculateRespBO.PromotionItem();
            promotionItem.setSkuId(orderItem.getSkuId());
            promotionItem.setTotalPrice(orderItem.getPayPrice());
            promotionItem.setDiscountPrice(discountPrices.get(i));
            promotionItems.add(promotionItem);
        }
        // 创建营销明细
        TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion();
        promotion.setId(id);
        promotion.setName(name);
        promotion.setType(type);
        promotion.setTotalPrice(calculateTotalPayPrice(orderItems));
        promotion.setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum));
        promotion.setItems(promotionItems);
        promotion.setMatch(true);
        promotion.setDescription(description);
        result.getPromotions().add(promotion);
    }

    /**
     * 添加【不匹配】多个 OrderItem 的营销明细
     *
     * @param result      价格计算结果
     * @param orderItems  多个订单产品 SKU
     * @param id          营销编号
     * @param name        营销名字
     * @param description 满足条件的提示
     * @param type        营销类型
     */
    public static void addNotMatchPromotion(TradePriceCalculateRespBO result, List<TradePriceCalculateRespBO.OrderItem> orderItems,
                                            Long id, String name, Integer type, String description) {
        // 创建营销明细 Item
        List<TradePriceCalculateRespBO.PromotionItem> promotionItems = CollectionUtils.convertList(orderItems,
                orderItem -> {
                    TradePriceCalculateRespBO.PromotionItem promotionItem = new TradePriceCalculateRespBO.PromotionItem();
                    promotionItem.setSkuId(orderItem.getSkuId());
                    promotionItem.setTotalPrice(orderItem.getPayPrice());
                    promotionItem.setDiscountPrice(0);
                    return promotionItem;
                });
        // 创建营销明细
        TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion();
        promotion.setId(id);
        promotion.setName(name);
        promotion.setType(type);
        promotion.setTotalPrice(calculateTotalPayPrice(orderItems));
        promotion.setDiscountPrice(0);
        promotion.setItems(promotionItems);
        promotion.setMatch(false);
        promotion.setDescription(description);
        result.getPromotions().add(promotion);
    }

    public static String formatPrice(Integer price) {
        return MoneyUtils.fenToYuanStr(NumberUtil.nullToZero(price));
    }

}
